package com.fla.puzzle.utils;

import java.io.Closeable;
import java.io.IOException;
import java.lang.reflect.Method;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.LinkedList;
import java.util.List;

import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface.OnClickListener;
import android.content.res.Configuration;
import android.net.Uri;
import android.util.Log;

/**
 * Contains different useful methods
 */
public class Utils {

    public static URI toURI(String string) {
        try {
            return new URI(Uri.encode(string));
        }
        catch (URISyntaxException e) {
            throw new IllegalArgumentException("Cannot create URI for: " + string, e);
        }
    }
    
    public static String fromURI(URI uri) {
        return Uri.decode(uri.toString());
    }

    /**
     * Describes predicate
     */
    public interface Predicate<T> {
        boolean evaluate(T object);
    }

    /**
     * Filter specified list.
     * 
     * <p>
     * Creates new list and fill its with items from sourceList which are evaluated to true by specified predicate.
     * </p>
     * 
     * @param sourceList List source list.
     * @param predicate Predicate a predicate to use to evaluate list object.
     * @return List filtered list.
     */
    public static <T> List<T> filter(List<T> sourceList, Predicate<T> predicate) {
        List<T> filteredList = new LinkedList<T>();
        for (T object : sourceList) {
            if (predicate.evaluate(object)) {
                filteredList.add(object);
            }
        }
        return filteredList;
    }

    public static void closeQuietly(Closeable closeable) {
        try {
            if (closeable != null) {
                closeable.close();
            }
        }
        catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    /**
     * Tests if the current device is a tablet not smartphone
     * 
     * @param context Context the invoking context
     * @return boolean true if the device is a tablet
     */
    public static boolean isTabletDevice(Context context) {
        if (android.os.Build.VERSION.SDK_INT >= 11) { // honeycomb
            // test screen size, use reflection because isLayoutSizeAtLeast is only available since 11
            Configuration config = context.getResources().getConfiguration();
            try {
                Method mIsLayoutSizeAtLeast = config.getClass().getMethod("isLayoutSizeAtLeast", int.class);

                // Configuration.SCREENLAYOUT_SIZE_XLARGE
                return (Boolean) mIsLayoutSizeAtLeast.invoke(config, 0x00000004);
            }
            catch (Exception e) {
                Log.e("test", "Cannot invoke method isLayoutSizeAtLeast", e);
            }
        }
        return false;
    }

    /**
     * Shows confirmation dialog with two buttons YES and NO.
     * 
     * @param context Context to use
     * @param message CharSequence title to display
     * @param message CharSequence message to display
     * @param okClick click listener for the button Yes
     */
    public static void showOkNoDialog(Context context, CharSequence title, CharSequence message, OnClickListener okClick) {
        new AlertDialog.Builder(context).setTitle(title).setMessage(message).setPositiveButton("Yes", okClick)
            .setNegativeButton("No", null).show();
    }

    /**
     * Shows dialog with 'not implemented' message
     * 
     * @param context Context to use
     */
    public static void showNotImplemented(Context context) {
        new AlertDialog.Builder(context).setTitle("Not implemented").setMessage("Feature is not implemented")
            .setPositiveButton("Ok", null).show();
    }
}
